/**
 * 文件导入服务
 * 负责扫描文件夹、导入图片文件到数据库
 */

import fs from 'fs'
import path from 'path'
import crypto from 'crypto'
import { app, ipcMain } from 'electron'
import { PhotoModel } from '../database'
import { ImageService } from './imageService'

/**
 * 文件导入进度信息
 */
export interface ImportProgress {
  total: number
  processed: number
  added: number
  skipped: number
  errors: number
  currentFile?: string
}

/**
 * 文件导入选项
 */
export interface ImportOptions {
  /** 是否递归导入子文件夹 */
  recursive: boolean
  /** 是否跳过重复文件 */
  skipDuplicates: boolean
  /** 是否生成缩略图 */
  generateThumbnails: boolean
  /** 支持的文件扩展名 */
  supportedExtensions: string[]
}

/**
 * 文件导入服务类
 */
export class FileImportService {
  private static instance: FileImportService
  private isImporting = false
  private importProgress: ImportProgress = {
    total: 0,
    processed: 0,
    added: 0,
    skipped: 0,
    errors: 0
  }

  /**
   * 获取文件导入服务实例
   * @returns 文件导入服务实例
   */
  public static getInstance(): FileImportService {
    if (!FileImportService.instance) {
      FileImportService.instance = new FileImportService()
    }
    return FileImportService.instance
  }

  /**
   * 注册IPC处理器
   */
  public registerIpcHandlers(): void {
    // 注意：这些处理器已经在photoIpc.ts中注册，这里不再重复注册
    // 如果需要添加新的处理器，请确保不与现有处理器冲突
    console.log('文件导入服务IPC处理器已注册')
  }

  /**
   * 导入文件夹
   * @param folderPath 文件夹路径
   * @param options 导入选项
   * @returns 导入结果
   */
  public async importFolder(
    folderPath: string,
    options: Partial<ImportOptions> = {}
  ): Promise<{ success: boolean; message: string }> {
    if (this.isImporting) {
      return { success: false, message: '已有导入任务在进行中' }
    }

    // 验证文件夹路径
    if (!fs.existsSync(folderPath) || !fs.statSync(folderPath).isDirectory()) {
      return { success: false, message: '无效的文件夹路径' }
    }

    // 设置默认选项
    const importOptions: ImportOptions = {
      recursive: true,
      skipDuplicates: true,
      generateThumbnails: true,
      supportedExtensions: ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.tiff', '.webp', '.heic', '.heif', '.raw'],
      ...options
    }

    // 开始导入
    this.isImporting = true
    this.importProgress = {
      total: 0,
      processed: 0,
      added: 0,
      skipped: 0,
      errors: 0
    }

    try {
      // 扫描文件
      const files = this.scanFolder(folderPath, importOptions)
      this.importProgress.total = files.length

      // 导入文件
      for (const filePath of files) {
        if (!this.isImporting) break // 检查是否取消导入

        this.importProgress.currentFile = filePath

        try {
          const result = await this.importFile(filePath, importOptions)
          if (result.added) {
            this.importProgress.added++
          } else {
            this.importProgress.skipped++
          }
        } catch (error) {
          console.error(`导入文件失败: ${filePath}`, error)
          this.importProgress.errors++
        }

        this.importProgress.processed++

        // 发送进度更新
        if (this.importProgress.processed % 10 === 0 || this.importProgress.processed === this.importProgress.total) {
          // 这里可以通过事件发送进度更新到渲染进程
          // 例如: this.mainWindow.webContents.send('import:progress', this.importProgress)
        }
      }

      return {
        success: true,
        message: `导入完成: 添加 ${this.importProgress.added} 个文件, 跳过 ${this.importProgress.skipped} 个文件, 错误 ${this.importProgress.errors} 个文件`
      }
    } catch (error) {
      console.error('导入文件夹失败', error)
      return { success: false, message: `导入失败: ${error instanceof Error ? error.message : '未知错误'}` }
    } finally {
      this.isImporting = false
      this.importProgress.currentFile = undefined
    }
  }

  /**
   * 扫描文件夹获取所有图片文件
   * @param folderPath 文件夹路径
   * @param options 导入选项
   * @returns 文件路径数组
   */
  private scanFolder(folderPath: string, options: ImportOptions): string[] {
    const files: string[] = []

    const scan = (dir: string) => {
      const entries = fs.readdirSync(dir, { withFileTypes: true })

      for (const entry of entries) {
        const fullPath = path.join(dir, entry.name)

        if (entry.isDirectory() && options.recursive) {
          // 递归扫描子文件夹
          scan(fullPath)
        } else if (entry.isFile()) {
          // 检查文件扩展名
          const ext = path.extname(entry.name).toLowerCase()
          if (options.supportedExtensions.includes(ext)) {
            files.push(fullPath)
          }
        }
      }
    }

    scan(folderPath)
    return files
  }

  /**
   * 导入单个文件
   * @param filePath 文件路径
   * @param options 导入选项
   * @returns 导入结果
   */
  private async importFile(filePath: string, options: ImportOptions): Promise<{ added: boolean; photoId?: number }> {
    // 检查文件是否已存在
    if (options.skipDuplicates) {
      const existingPhoto = PhotoModel.getByFilePath(filePath)
      if (existingPhoto) {
        return { added: false }
      }
    }

    // 获取文件信息
    const stats = fs.statSync(filePath)
    const fileName = path.basename(filePath)
    const fileSize = stats.size
    const createdAt = stats.birthtime.toISOString()
    const modifiedAt = stats.mtime.toISOString()

    // 计算文件哈希
    const fileHash = await this.calculateFileHash(filePath)

    // 检查哈希是否已存在
    if (options.skipDuplicates) {
      const existingPhoto = PhotoModel.getByFileHash(fileHash)
      if (existingPhoto) {
        return { added: false }
      }
    }

    // 获取图片信息
    const imageInfo = await ImageService.getImageInfo(filePath)

    // 生成缩略图和预览图
    let thumbnailPath: string | undefined
    let previewPath: string | undefined

    if (options.generateThumbnails) {
      try {
        const userDataPath = app.getPath('userData')
        const thumbnailsDir = path.join(userDataPath, 'thumbnails')
        const previewsDir = path.join(userDataPath, 'previews')

        // 确保目录存在
        if (!fs.existsSync(thumbnailsDir)) {
          fs.mkdirSync(thumbnailsDir, { recursive: true })
        }
        if (!fs.existsSync(previewsDir)) {
          fs.mkdirSync(previewsDir, { recursive: true })
        }

        // 生成缩略图和预览图
        thumbnailPath = path.join(thumbnailsDir, `${fileHash}_thumb.jpg`)
        previewPath = path.join(previewsDir, `${fileHash}_preview.jpg`)

        await ImageService.generateThumbnail(filePath, thumbnailPath, 200, 200)
        await ImageService.generateThumbnail(filePath, previewPath, 800, 600)
      } catch (error) {
        console.error('生成缩略图失败', error)
        // 缩略图生成失败不影响文件导入
      }
    }

    // 创建照片记录
    const photoData = {
      file_path: filePath,
      file_name: fileName,
      file_size: fileSize,
      file_hash: fileHash,
      width: imageInfo.width,
      height: imageInfo.height,
      format: imageInfo.format,
      created_at: createdAt,
      modified_at: modifiedAt,
      captured_at: imageInfo.exif?.DateTimeOriginal,
      camera_make: imageInfo.exif?.Make,
      camera_model: imageInfo.exif?.Model,
      latitude: imageInfo.exif?.GPSLatitude,
      longitude: imageInfo.exif?.GPSLongitude,
      altitude: imageInfo.exif?.GPSAltitude,
      thumbnail_path: thumbnailPath,
      preview_path: previewPath,
      rating: 0,
      description: ''
    }

    const photoId = PhotoModel.insert(photoData)
    return { added: true, photoId }
  }

  /**
   * 计算文件哈希
   * @param filePath 文件路径
   * @returns 文件哈希
   */
  private async calculateFileHash(filePath: string): Promise<string> {
    return new Promise((resolve, reject) => {
      const hash = crypto.createHash('sha256')
      const stream = fs.createReadStream(filePath)

      stream.on('data', (data) => {
        hash.update(data)
      })

      stream.on('end', () => {
        resolve(hash.digest('hex'))
      })

      stream.on('error', (error) => {
        reject(error)
      })
    })
  }
}